/****************************************************************************
 *
 * Copyright (C) 2003-2010 Los Alamos National Security, LLC
 *                         Packet Analytics Corporation
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License Version 2 as
 * published by the Free Software Foundation.  You may not use, modify or
 * distribute this program under any other version of the GNU General
 * Public License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 ****************************************************************************/
/**
 * 
 */
package nfse.dataset.snort;

import java.io.RandomAccessFile;
import java.sql.Date;
import java.sql.Timestamp;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.GZIPInputStream;

import nfse.NetFSERecord;
import nfse.NetFSEUtil;
import nfse.gui.record.FlexRecordField;
import nfse.gui.server.GUIRecordFactory;
import nfse.gui.server.RecordBuilderUtil;

/**
 * @author bduphoff
 * 
 */
public class SnortRecordFactory extends GUIRecordFactory<SnortRecord> {

    public SnortRecordFactory() {
        builder = new RecordBuilderUtil();
        builder.addColumn(null, "id", RecordBuilderUtil.BIGINT);
        RecordBuilderUtil.SQLField field = builder.addColumn("Start TS", "startts", RecordBuilderUtil.TIMESTAMP);
        field = builder.addColumn("Src IP", "srcip", RecordBuilderUtil.INET);
        field = builder.addColumn("Src Port", "srcport", RecordBuilderUtil.INTEGER);
        field.setSubtype(FlexRecordField.SUB_TYPE_PORT);
        field = builder.addColumn("Dst IP", "dstip", RecordBuilderUtil.INET);
        field = builder.addColumn("Dst Port", "dstport", RecordBuilderUtil.INTEGER);
        field.setSubtype(FlexRecordField.SUB_TYPE_PORT);
        field = builder.addColumn("Protocol", "protocol", RecordBuilderUtil.INTEGER);
        field.setSubtype(FlexRecordField.SUB_TYPE_PROTOCOL);
        field = builder.addColumn("SID", "sid", RecordBuilderUtil.INTEGER);
        field = builder.addColumn("CID", "cid", RecordBuilderUtil.INTEGER);
        field = builder.addColumn("Priority", "priority", RecordBuilderUtil.INTEGER);
        field = builder.addColumn("Classification", "classification", RecordBuilderUtil.VARCHAR, 255);
        field = builder.addColumn("Description", "description", RecordBuilderUtil.VARCHAR, 255);
    }

    @Override
    protected void setValues(SnortRecord record, int id) {
        int idx = -1;
        builder.setFieldValue(++idx, "" + id);
        builder.setFieldValue(++idx, "" + record.getStartTS());
        builder.setFieldValue(++idx, record.getSrcAddr());
        builder.setFieldValue(++idx, "" + record.srcPort);
        builder.setFieldValue(++idx, record.getDstAddr());
        builder.setFieldValue(++idx, "" + record.dstPort);
        builder.setFieldValue(++idx, "" + record.proto);
        builder.setFieldValue(++idx, "" + record.sid);
        builder.setFieldValue(++idx, "" + record.cid);
        builder.setFieldValue(++idx, "" + record.priority);
        builder.setFieldValue(++idx, NetFSEUtil.prepareValueForInsert(record.classification));
        builder.setFieldValue(++idx, NetFSEUtil.prepareValueForInsert(record.sigName));
    }

    /*
     * (non-Javadoc)
     * 
     * @see nfse.NetFSERecordFactory#generate(java.lang.String, int)
     */
    @Override
    public NetFSERecord generate() {
        return new SnortRecord();
    }

    @Override
    public NetFSERecord generate(String line, int sensor) throws Exception {
        SnortRecord rec = new SnortRecord(sensor);
        // System.out.println(line);
        rec.setInitialString(line);
        rec.setTypeID(typeID);
        rec.setTypeName(typeName);
        line = line.trim();
        String[] lines = line.split("\n");

        for (int x = 0; x < lines.length; x++) {
            String[] lines2 = lines[x].split("\n");
            for (int i = 0; i < lines2.length; i++) {

                // System.out.println("line " + (i) + ": '" + lines[i] + "'");
                lines2[i] = lines2[i].trim();
                if (lines2[i].length() == 0) {
                    // ignore
                } else if (lines2[i].startsWith("[**")) {
                    Pattern p = Pattern.compile("\\[\\*\\*\\] \\[([0-9:]+)\\] (.*) \\[\\*\\*\\]");
                    Matcher m = p.matcher(lines2[0]);
                    boolean b = m.matches();
                    if (b) {
                        rec.sigName = m.group(2);
                        String value2 = m.group(1);
                        String[] sigValues = value2.split(":");
                        rec.sid = Integer.parseInt(sigValues[2]);
                        rec.cid = Integer.parseInt(sigValues[1]);
                        rec.sigClassID = Integer.parseInt(sigValues[0]);
                    }
                } else if (lines2[i].startsWith("[Class")) {
                    Pattern p = Pattern.compile("\\[(.*)\\] \\[(.*)\\]");
                    Matcher m = p.matcher(lines2[i]);
                    boolean b = m.matches();
                    rec.classification = m.group(1).substring(16);
                    String value2 = m.group(2);
                    rec.priority = Integer.parseInt(value2.substring(10));
                } else if (lines2[i].startsWith("[Xref ")) {
                    rec.refLine = lines2[i];
                } else if (lines2[i].startsWith("TCP ") || lines2[i].startsWith("ICMP ")
                        || lines2[i].startsWith("UDP ")) {
                    String[] values = lines2[i].split(" ");
                    rec.proto = SnortRecord.convertFromSnortProtocol(values[0]);
                } else {
                    try {
                        String[] values = lines2[i].split(" ");
                        rec.setTimestamp(SnortRecord.convertFromSnortTS(values[0]));

                        boolean testing = true;
                        if (testing) {
                            Timestamp ts = rec.getTimestamp();
                            String tsStr = ts.toString();
                            if (ts.before(Date.valueOf("1999-01-01"))) {
                                tsStr = "2007" + tsStr.substring(4);
                            } else if (ts.before(Date.valueOf("2000-01-01"))) {
                                tsStr = "2008" + tsStr.substring(4);
                            } else if (ts.before(Date.valueOf("2001-01-01"))) {
                                tsStr = "2009" + tsStr.substring(4);
                            }
                            rec.setTimestamp(Timestamp.valueOf(tsStr));
                        }

                        int idx = 1;
                        if (values[idx].startsWith("{")) {
                            rec.proto = NetFSEUtil.getProtocol(values[idx].substring(1, values[idx].length() - 1));
                            idx++;
                        }

                        String srcIP = "";
                        int srcPort = -1;
                        String[] srcValues = values[idx].split(":");
                        if (srcValues.length <= 1) {
                            srcIP = values[idx];
                        } else {
                            srcIP = srcValues[0];
                            srcPort = Integer.parseInt(srcValues[1]);
                        }
                        rec.setSrcAddr(srcIP);
                        rec.srcPort = srcPort;

                        idx += 2;

                        String dstIP = "";
                        int dstPort = -1;
                        String[] dstValues = values[idx].split(":");
                        if (dstValues.length <= 1) {
                            dstIP = values[idx];
                        } else {
                            dstIP = dstValues[0];
                            dstPort = Integer.parseInt(dstValues[1]);
                        }
                        rec.dstPort = dstPort;

                        rec.setSrcIP(NetFSEUtil.convertIPtoLong(rec.getSrcAddr()));
                        rec.setDstIP(NetFSEUtil.convertIPtoLong(dstIP));

                        // System.out.println(srcIP + "," + srcPort + "," +
                        // dstIP +
                        // "," +
                        // dstPort);

                    } catch (Exception e) {
                        rec.content.addElement(lines2[i]);
                        // System.out.println("---Bad line alert---");
                        // System.out.println(lines2[i]);
                        // e.printStackTrace();
                        // System.out.println(line.split("\n").length);
                    }
                }
            }
        }
        if (rec.getTimestamp() == null)
            return null;

        return rec;
    }

    public String getRecordLine(RandomAccessFile dataIn) {
        try {
            StringBuilder temp = new StringBuilder();
            String line = dataIn.readLine();
            while (line != null && (line = line.trim()).length() > 0) {
                // System.out.println("SNORT: '" + line + "'");
                temp.append(line + "\n");
                line = dataIn.readLine();
            }
            // System.out.println(temp.toString());
            return temp.toString();
        } catch (Exception e) {

        }
        return null;
    }

    public String getRecordLine(GZIPInputStream dataIn) {
        try {
            StringBuilder line = new StringBuilder();
            int ch = 0;
            do {
                ch = dataIn.read();
                line.append((char) ch);

            } while ((ch != -1) && (line.indexOf("\n\n") == -1));
            // System.out.println("Zipped Line: " + line);
            return line.toString().substring(0, line.length() - 1);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

}
